package com.qiangesoft.rdp.starter.minio.config;

import com.qiangesoft.rdp.starter.minio.core.MinioTemplate;
import com.qiangesoft.rdp.starter.minio.core.MinioTemplateImpl;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * minio自动配置
 *
 * @author qiangesoft
 * @date 2023-09-15
 */
@Slf4j
@Configuration
@ConditionalOnClass(value = {MinioClient.class})
@RequiredArgsConstructor
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfiguration {

    private final MinioProperties minioProperties;

    @Bean
    @ConditionalOnMissingBean
    public MinioClient minioClient() {
        log.info("MinioClient initializing, url is {}, accessKey is {}!", minioProperties.getEndpoint(), minioProperties.getAccessKey());

        MinioClient.Builder builder = MinioClient
                .builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey());
        String region = minioProperties.getRegion();
        if (region != null && region.length() > 0) {
            builder.region(region);
        }
        MinioClient minioClient = builder.build();

        // 设置超时时间
        minioClient.setTimeout(
                minioProperties.getConnectTimeout(),
                minioProperties.getWriteTimeout(),
                minioProperties.getReadTimeout()
        );

        List<MinioProperties.Bucket> bucketList = minioProperties.getBuckets();
        if (bucketList == null) {
            log.error("Buckets not empty");
            throw new RuntimeException("Buckets not empty");
        }

        // 校验桶
        this.checkBucket(bucketList);

        // 初始化桶
        for (MinioProperties.Bucket bucket : bucketList) {
            String bucketName = bucket.getName();
            if (!this.checkExists(minioClient, bucketName)) {
                this.createBucket(minioClient, bucketName);
            }
        }

        log.info("MinioClient initialization success!");
        return minioClient;
    }

    @Bean
    @ConditionalOnMissingBean
    public MinioTemplate minioTemplate() {
        return new MinioTemplateImpl(minioProperties, minioClient());
    }

    /**
     * 校验需要存在默认的桶
     *
     * @return
     */
    private void checkBucket(List<MinioProperties.Bucket> bucketList) {
        long count = bucketList.stream().filter(MinioProperties.Bucket::getIsDefault).count();
        if (count == 0) {
            log.error("Default bucket not exists");
            throw new RuntimeException("Default bucket not exists");
        }
        if (count > 1) {
            log.error("Default bucket num > 1");
            throw new RuntimeException("Default bucket num > 1");
        }
    }

    /**
     * 检查桶是否存在
     *
     * @param minioClient
     * @param bucketName
     * @return
     */
    private boolean checkExists(MinioClient minioClient, String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error("Check bucket exists failed with error");
            throw new RuntimeException("Check bucket exists failed with error");
        }
    }

    /**
     * 创建桶
     *
     * @param minioClient
     * @param bucketName
     */
    private void createBucket(MinioClient minioClient, String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            log.error("Create bucket failed with error");
            throw new RuntimeException("Create bucket failed with error");
        }
    }
}
